/******************************************************************************* * Copyright (c) 2010-2015 Henshin developers. All rights reserved. * This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * TU Berlin, University of Luxembourg, SES S.A. *******************************************************************************/ /** * */ package de.tub.tfs.muvitor.actions; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.draw2d.Graphics; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.SWTGraphics; import org.eclipse.draw2d.Viewport; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.gef.EditPartViewer; import org.eclipse.gef.GraphicalEditPart; import org.eclipse.gef.editparts.SimpleRootEditPart; import org.eclipse.gef.ui.actions.SelectionAction; import org.eclipse.gmf.runtime.draw2d.ui.render.awt.internal.svg.export.GraphicsSVG; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Device; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.ImageLoader; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.dialogs.SaveAsDialog; /** * This action exports the whole EditPartViewer containing some selected * GraphicalEditPart to a png, jpeg, or bmp image file. * * @author Tony Modica * */ public class ExportViewerImageAction extends SelectionAction { public static final String ID = "ExportViewerImageAction"; private static int counter = 1; /** * The viewer containing the currently selected GraphicalEditPart */ private EditPartViewer viewer = null; public ExportViewerImageAction(final IWorkbenchPart part) { super(part); setId(ID); setText("Export viewer image"); setImageDescriptor(PlatformUI.getWorkbench().getSharedImages() .getImageDescriptor(ISharedImages.IMG_ETOOL_SAVE_EDIT)); } /** * Ask for a file name and save the viewer containing the currently selected * GraphicalEditPart to a image file. */ @Override public void run() { final IEditorInput editorInput = (IEditorInput) getWorkbenchPart().getAdapter( IEditorInput.class); final SaveAsDialog dialog = new SaveAsDialog(new Shell(Display.getDefault())); dialog.setBlockOnOpen(true); if (editorInput == null) { dialog.setOriginalName("viewerImage" + counter + ".png"); } else { final String fileName = editorInput.getName(); final int extensionPos = fileName.lastIndexOf("."); dialog.setOriginalName(fileName.substring(0, extensionPos) + ".png"); } dialog.create(); dialog.setMessage("If you don't choose an extension png will be used a default. " + "\n" + "Export is limited to file size of 15MByte -> you may use file ..(read more) " + "\n" + "type svg for very large graphs." + "\n" + "After export the workspace needs a manual refresh to show new image file."); dialog.setTitle("Specify file to export viewer image (png, jpeg, bmp, svg)"); dialog.open(); if (Window.CANCEL == dialog.getReturnCode()) { return; } final IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); final IPath path = root.getLocation().append(dialog.getResult()); int format; final String ext = path.getFileExtension(); if (ext.equals("png")) { format = SWT.IMAGE_PNG; // GIFs work only with 8Bit and not with 32 Bits color depth // } else if (ext.equals("gif")) { // format = SWT.IMAGE_GIF; } else if (ext.equals("jpeg")) { format = SWT.IMAGE_JPEG; } else if (ext.equals("bmp")) { format = SWT.IMAGE_BMP; // } else if (ext.equals("ico")) { // format = SWT.IMAGE_ICO; } else if (ext.equalsIgnoreCase("svg")) { format = SWT.IMAGE_UNDEFINED; // TODO: find a more appropriate constant for representing SVGs } else { MessageDialog.openError(null, "Invalid file extension!", "The specified extension (" + ext + ") is not a valid image format extension.\nPlease use png, jpeg, bmp or svg!"); return; } IFigure figure = ((SimpleRootEditPart) viewer.getRootEditPart()).getFigure(); if (figure instanceof Viewport) { // This seems to trim the figure to the smallest rectangle containing all child figures ((Viewport) figure).setSize(1, 1); ((Viewport) figure).validate(); figure = ((Viewport) figure).getContents(); } if (format == SWT.IMAGE_UNDEFINED) { try { final File file = path.toFile(); this.exportToSVG(file, figure); } catch (final IOException e) { e.printStackTrace(); } } else { final byte[] imageCode = createImage(figure, format); try { final File file = path.toFile(); final FileOutputStream fos = new FileOutputStream(file); fos.write(imageCode); fos.flush(); fos.close(); counter++; } catch (final IOException e) { e.printStackTrace(); } } } /** * Export an image to SVG file format. * * @param file * @param rootFigure * @throws IOException */ public void exportToSVG(File file, IFigure rootFigure) throws IOException { Rectangle bounds = rootFigure.getBounds(); GraphicsSVG graphics = GraphicsSVG.getInstance(bounds.getTranslated(bounds.getLocation().negate())); graphics.translate(bounds.getLocation().negate()); rootFigure.paint(graphics); // graphics.getSVGGraphics2D().stream(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)))); // FIXME: SVG export is not working any more due to API restrictions of GMF } /** * Returns the bytes of an encoded image for the specified IFigure in the * specified format. * * @param figure * the Figure to create an image for. * @param format * one of SWT.IMAGE_BMP, SWT.IMAGE_BMP_RLE, SWT.IMAGE_GIF * SWT.IMAGE_ICO, SWT.IMAGE_JPEG, or SWT.IMAGE_PNG * @return the bytes of an encoded image for the specified Figure */ private byte[] createImage(final IFigure figure, final int format) { final Device device = viewer.getControl().getDisplay(); final Rectangle r = figure.getBounds(); final ByteArrayOutputStream result = new ByteArrayOutputStream(); Image image = null; GC gc = null; Graphics g = null; try { image = new Image(device, r.width, r.height); gc = new GC(image); g = new SWTGraphics(gc); g.translate(r.x * -1, r.y * -1); figure.paint(g); final ImageLoader imageLoader = new ImageLoader(); imageLoader.data = new ImageData[] { image.getImageData() }; imageLoader.save(result, format); } catch(Exception e){ // the image size may not exceed 16M, svg requires less space for graphs than png and jpeg e.printStackTrace(); } finally { if (g != null) { g.dispose(); } if (gc != null) { gc.dispose(); } if (image != null) { image.dispose(); } } return result.toByteArray(); } /** * This action is enabled if a GraphicalEditPart is selected. * * @see org.eclipse.gef.ui.actions.WorkbenchPartAction#calculateEnabled() */ @Override protected boolean calculateEnabled() { if (getSelection() == null || !(getSelection() instanceof IStructuredSelection)) { return false; } final Object firstSelection = ((IStructuredSelection) getSelection()).getFirstElement(); if (firstSelection == null || !(firstSelection instanceof GraphicalEditPart)) { return false; } viewer = ((GraphicalEditPart) firstSelection).getRoot().getViewer(); return true; } }